#include "include/comment.h"
#include "include/keyboard.h"
#include <string.h>

const unsigned char kbScanCodes[512] =    
/// Keyboard character maps (Look-up table)
{					
	0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0,
	'0', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[' , ']', 0, 0,
	'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0,
	'\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0,
	'*', 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, '-', 0, 0, 0, '+', 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	/* Shifted */
	0, 27, '!', '@', '#', '$', '%', '^', '&', '*', '(' , ')', '_' , '+', 0,
	'0', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{' , '}', 0, 0,
	'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '\"', '~', 0,
	'|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 0,
	'*', 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, '7', '8', '9', 0, '4', '5', '6', 0,
	'1', '2', '3', '0', 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	/* Caps, Normal */
	0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0,
	'0', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{' , '}', 0, 0,
	'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '\'', '~', 0,
	'|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 0,
	'*', 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, '-', 0, 0, 0, '+', 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	/* Caps, Shifted */
	0, 27, '!', '@', '#', '$', '%', '^', '&', '*', '(' , ')', '_' , '+', 0,
	'0', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[' , ']', 0, 0,
	'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\"', '`', 0,
	'\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0,
	'*', 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, '-', 0, 0, 0, '+', 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

static	KEYBOARDMSG *keyboard_msg;
static	KEYBOARDBUFF *keyboard_buff;
static	KEYBOARDPOS	*keyboard_pos;

static	unsigned int shell_message_ip;
static	char shell_message_array[64];

void keyboard_install(const void *addr)
{
	keyboard_msg = (KEYBOARDMSG *)addr;
	keyboard_msg -> src_data[0] = 0;
	keyboard_msg -> src_data[1] = 0;
	keyboard_msg -> shift = 0;
	keyboard_msg -> caps = 0;

	keyboard_buff = (KEYBOARDBUFF *)((int)keyboard_msg + sizeof(KEYBOARDMSG));
	keyboard_buff -> push_ip = 0;
	keyboard_buff -> pop_ip = 0;

	keyboard_pos = (KEYBOARDPOS *)((int)keyboard_buff + sizeof(KEYBOARDBUFF));
	keyboard_pos -> pb = 0;
	keyboard_pos -> pp = 0;

	shell_message_ip = 1;
	memset(shell_message_array, 0, 64);

}

void keyboard_run()
{

#if 1
	// 双响应键
	switch(keyboard_msg -> src_data[1])
	{
		case 42: ;	// shift 按下
		case 54:
				 {
					 keyboard_msg -> shift = 1;
				 }
				 break;
		case 42 + 128: ;	// shift 放开
		case 54 + 128:
					   {
						   keyboard_msg -> shift = 0;
					   }
					   break;
		default:
					   break;
	}
#endif

#if 1
	if(keyboard_buff -> pop_ip != keyboard_buff -> push_ip)
	{
		/*
		   putc_ex(0, 0, kbScanCodes[keyboard_buff -> buff[keyboard_buff -> pop_ip]]);

		   if(keyboard_buff -> pop_ip < 32)
		   {
		   keyboard_buff -> pop_ip++;
		   }
		   else
		   {
		   keyboard_buff -> pop_ip = 0;
		   }
		 */

		// 单响应键
		switch(keyboard_buff -> buff[keyboard_buff -> pop_ip])
		{
			case 58:	// capslk
				{

					if(0 == keyboard_msg -> caps)
					{
						keyboard_msg -> caps = 2;
					}
					else
					{
						keyboard_msg -> caps = 0;
					}
				}
				break;
			case 28:	// enter
				{
					//keyboard_pos -> pb += (keyboard_pos -> pp / 80 + 1);
					//keyboard_pos -> pp += 80 - keyboard_pos -> pp;
					keyboard_pos -> pp = 9;
					puts_ex(23, 9, "                                ");
					puts_ex(23, 9 + 32, "                                ");

					// 消息队列处理
					send_message_shell(shell_message_array + 1);
					//puts_ex(7, 4, shell_message_array + 1);

					shell_message_ip = 1;
					memset(shell_message_array, 0, 64);
				}
				break;
			case 14:	// bakspace
				{
					/*
					   if(keyboard_pos -> pp > 0)
					   {
					   keyboard_pos -> pp --;
					   }
					   else 
					   {
					   keyboard_pos -> pp = 79;
					   keyboard_pos -> pb --;
					   }
					 */
					putc_ex(23, -- keyboard_pos -> pp, ' ');
					
					if(0 == shell_message_array[0])
					{
						shell_message_array[-- shell_message_ip] = 0;
					}
				}
				break;
			case 15:	// tab
				{
					//keyboard_pos -> pb += (keyboard_pos -> pp / 80);
					//keyboard_pos -> pp %= 80;

					if((keyboard_pos -> pp += 4) > 79)
					{
						keyboard_pos -> pp = 79;
					}

					// 放入指令处理队列
					if(0 != shell_message_array[1])
					{
						shell_message_array[0] = 1;
						//puts_ex(8, 4, shell_message_array + 1);
					}
				}
				break;

			default:
				{
					//	常用字符
					if(0 != kbScanCodes[keyboard_buff -> buff[keyboard_buff -> pop_ip]])
					{
						putc_ex(23, 
								keyboard_pos -> pp ++,
								kbScanCodes[keyboard_buff -> buff[keyboard_buff -> pop_ip] + 
								128 * (keyboard_msg -> shift + keyboard_msg -> caps)]);

						// 放入指令处理队列
						if(' ' != kbScanCodes[keyboard_buff -> buff[keyboard_buff -> pop_ip]] && 
						   '\0' != kbScanCodes[keyboard_buff -> buff[keyboard_buff -> pop_ip]])
						{
							if(0 == shell_message_array[0])
							{
								shell_message_array[shell_message_ip ++] = kbScanCodes[keyboard_buff -> buff[keyboard_buff -> pop_ip]];
								//puts_ex(8, 4, shell_message_array + 1);
							}
						}
						else
						{
							if(0 != shell_message_array[1])
							{
								shell_message_array[0] = 1;
								//puts_ex(8, 4, shell_message_array + 1);
							}
						}
					}

				}
				break;
		}


		if(keyboard_buff -> pop_ip < 32)
		{
			keyboard_buff -> pop_ip ++;
		}
		else
		{
			keyboard_buff -> pop_ip = 0;
		}

	}
#endif

#if 0
	// 键盘码缓冲区入值
	if(1 == keyboard_msg -> src_data[0] && keyboard_msg -> src_data[1] <= 128 )
	{
		keyboard_buff -> buff[keyboard_buff -> push_ip] = keyboard_msg -> src_data[1];

		if(keyboard_buff -> push_ip < 32)
		{
			keyboard_buff -> push_ip ++;
		}
		else
		{
			keyboard_buff -> push_ip = 0;
		}

		keyboard_msg -> src_data[0] = 0;
	}
	//	键盘码缓冲区入值 END.
#endif

	// TEST CODE
	//puti_ex(0, 10, keyboard_buff -> push_ip);
	//return;

#if 0
	//	键盘码缓冲区出值
	if(keyboard_buff -> pop_ip != keyboard_buff -> push_ip)
	{
		// 单响应键
		switch(keyboard_msg -> src_data[1])
		{
			case 58:	// capslk
				{

					if(0 == keyboard_msg -> caps)
					{
						keyboard_msg -> caps = 2;
					}
					else
					{
						keyboard_msg -> caps = 0;
					}
				}
				break;
			case 28:	// enter
				{
					keyboard_pos -> pb += (keyboard_pos -> pp / 80 + 1);
					keyboard_pos -> pp = 0;
				}
				break;
			case 14:	// bakspace
				{
					if(keyboard_pos -> pp > 0)
					{
						keyboard_pos -> pp --;
					}
					else 
					{
						keyboard_pos -> pp = 79;
						keyboard_pos -> pb --;
					}

					putc_ex(keyboard_pos -> pb, keyboard_pos -> pp, '\0');
				}
				break;
			case 15:	// tab
				{
					keyboard_pos -> pb += (keyboard_pos -> pp / 80);
					keyboard_pos -> pp %= 80;

					if((keyboard_pos -> pp += 4) > 79)
					{
						keyboard_pos -> pp = 79;
					}
				}
				break;

			default:
				{
					//	常用字符
					if(0 != kbScanCodes[keyboard_buff -> buff[keyboard_buff -> pop_ip]])
					{
						putc_ex(keyboard_pos -> pb, 
								keyboard_pos -> pp ++,
								kbScanCodes[keyboard_buff -> buff[keyboard_buff -> pop_ip] + 
								128 * (keyboard_msg -> shift + keyboard_msg -> caps)]);
					}
				}
				break;
		}

		if(keyboard_buff -> pop_ip < 32)
		{
			keyboard_buff -> pop_ip ++;
		}
		else
		{
			keyboard_buff -> pop_ip = 0;
		}
		//	键盘码缓冲区出值 END.
	}
#endif

}
